#pragma once
#include <iostream>
#include "Thread.hpp"
#include "LockGuard.hpp"
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <unordered_map>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>

using namespace std;

class UdpServer
{
public:
    UdpServer(string ip,uint16_t port,int sock)
    :_ip(ip)
    ,_port(port)
    ,_sock(-1)
    {

    }
    bool init_udp_server()
    {
        _sock=socket(AF_INET,SOCK_DGRAM,0);
        if(_sock < 0)
        {
            cout<<"init_udp_server failed"<<endl;
            exit(-1);
        }
        struct sockaddr_in server;
        bzero(&server,sizeof(server));
        server.sin_family=AF_INET;
        server.sin_port=htons(_port);
        server.sin_addr=inet_aton(_ip.c_str());

        int ret=bind(_sock,(struct sockaddr*)&server,sizeof(server));
        if(ret < 0)
        {
            cout<<"bind() failed"<<endl;
            close(_sock);
            exti(-2);
        }
        return true;
    }
    void start()
    {
        char buffer[1024];
        char key[256];
        while(true)
        {
            struct sockaddr_in client;
            socklen_t len=sizeof(client);
            string client_ip=inet_ntoa(client.sin_addr);
            uint16_t client_port=ntohs(client.sin_port);
            ssize_t s=recvfrom(_sock,buffer,sizeof(buffer),0,(struct sockaddr*)&client,&len);
            if(s > 0)
            {
                snprintf(key,sizeof(key),"%s-%u",client_ip,client_port);
                auto it=_users.find(key);
                if(it==_users.end())
                {
                    _users.insert({key,client});
                }
            }
            for(auto& iter:_users)
            {
                string sendMessage=key;
                sendMessage+="#";
                sendMessage+=buffer;
                sendto(_sock,sendMessage.c_str(),sizeof(sendMessage),0,(struct sockaddr*)&client,len);
            }
        }
    }
    ~UdpServer()
    {
        if(_sock)
        {
            close(_sock);
        }
    }
private:
    string _ip;
    uint16_t _port;
    int _sock;
    unordered_map<string,struct sockaddr_in> _users;
}
// class UdpServer
// {
// public:
//     UdpServer(string ip,uint16_t port)
//     :_sock(-1)
//     ,_ip(ip)
//     ,_port(port)
//     {

//     }
//     bool init_udp_server()
//     {
//         _sock=socket(AF_INET,SOCK_DGRAM,0);
//         if(_sock < 0)
//         {
//             cout<<"init_udp_server() failed"<<endl;
//             exit(-1);
//         }
//         struct sockaddr_in server;
//         socklen_t len=sizeof(server);
//         bzero(&server,sizeof(server));
//         server.sin_family=AF_INET;
//         server.sin_port=htons(_port);
//         server.sin_addr.s_addr=_ip.empty()?INADDR_ANY:(_ip.c_str());
//         int ret=bind(_sock,(struct sockaddr*)&server,len);
//         if(ret < 0)
//         {
//             cout<<"Udp_bind() failed"<<endl;
//             exit(-2);
//         }
//         return true;
//     }
//     void start()
//     {
//         char buffer[1024];
//         struct sockaddr_in client;
//         socklen_t len=sizeof(client);
//         bzero(&client,sizeof(client));
//         char key[1024];
//         ssize_t s=recvfrom(_sock,buffer,sizeof(buffer),0,(struct sockaddr_in*)&client,&len);
//         if(s > 0)
//         {
//             buffer[s]=0;
//             uint16_t client_port=ntohs(client.sin_port);
//             string client_ip=inet_ntoa(client.sin_addr);
//             snprintf(key,sizeof(key),"%s-%u",client_ip.c_str(),client_port);
//             auto it=_users.find(key);
//             if(it==_users.find(key))
//             {
//                 _users.insert({key,client});
//             }
//         }
//         for(auto& iter:_users)
//         {
//             string sendMessage=key;
//             sendMessage+="#";
//             sendMessage+=buffer;
//             sendto(_sock,sendMessage.c_str(),sizeof(sendMessage),0,(struct sockaddr*)&client,len);
//         }
//     }
//     ~UdpServer()
//     {
//         if(_sock)
//         {
//             close(_sock);
//         }
//     }
// private:
//     string _ip;
//     uint16_t _port;
//     int _sock;
//     unordered_map<string,struct sockaddr_in> _users;
// };

// class UdpServer
// {
// public:
//     UdpServer(string ip,uint16_t port)
//     :_ip(ip)
//     ,_port(port)
//     ,_sock(-1)
//     {

//     }
//     bool InitUdpServer()
//     {
//         _sock=socket(AF_INET,SOCK_DGRAM,0);
//         if(_sock < 0)
//         {
//             cout<<"initSock failed"<<endl;
//             exit(2);
//         }
//         struct sockaddr_in server;
//         bzero(&server,sizeof(server));
//         server.sin_family=AF_INET;
//         server.sin_port=htons(_port);
//         //这一个接口就可以将网络地址转为四个字节，并且有网络字节序转为主机字节序
//         server.sin_addr.s_addr=_ip.empty()?INADDR_ANY:inet_addr(_ip.c_str());
//         int ret=bind(_sock,(struct sockaddr*)&server,sizeof(server));
//         if(ret < 0)
//         {
//             cout<<"InitUdpServer failed"<<endl;
//             exit(3);
//         }
//     }
//     void start()
//     {
//         char buffer[1024];
//         struct sockaddr_in client;
//         socklen_t len=sizeof(client);
//         char result[1024];
//         char key[256];
//         ssize_t s=recvfrom(_sock,buffer,sizeof(buffer),0,(struct sockaddr*)&client,len);
//         if(s > 0)
//         {
//             string client_ip=inet_ntoa(client.sin_addr);
//             uint16_t client_port=ntohs(client.sin_port);
//             snprintf(key,sizeof(key),"%s-%u",client_ip.c_str(),client_port);
//             auto it=_users.find(key);
//             if(it==_users.end())
//             {
//                 _users.insert({key,client});
//             }
//         }
//         //我们这里要将接收到的数据包发送给我们网络当中的每一个用户
//         for(auto& iter:_users)
//         {
//             string sendMessage=key;
//             sendMessage+="#";
//             sendMessage+=buffer;
//             sendto(_sock,sendMessage,sizeof(sendMessage),0,(struct sockaddr*)&client,len);
//         }
//     }
//     ~UdpServer()
//     {
//         if(_sock >= 0)
//         {
//             close(_sock);
//         }
//     }
// private:
//     string _ip;
//     uint16_t _port;
//     int _sock;
//     unordered_map<string,struct sockaddr_in> _users;
// };
// class UdpServer
// {
// public:
//     UdpServer(uint16_t port,string ip="")
//     :_ip(ip)
//     ,_port(port)
//     ,_sock(-1)
//     {

//     }
//     bool InitUdpServer()
//     {
//         _sock=socket(AF_INET,SOCK_DGRAM,0);
//         if(_sock < 0)
//         {
//             cout<<"InitUdpServer failed"<<endl;
//             exit(1);
//         }
//         struct sockaddr_in server;
//         bzero(&server,sizeof(server));
//         server.sin_family=AF_INET;
//         server.sin_port=htons(_port);
//         //首先我们这里要将点分十进制的数据转换成为四个字节然后我们还要
//         //将四个字节的主机序列转换成为网络序列
//         server.sin_addr.s_addr=_ip.empty()?INADDR_ANY:inet_addr(_ip.c_str());
//         int ret=bind(_sock,(struct sockaddr*)&server,sizeof(server));
//         if(ret < 0)
//         {
//             cout<<"bind() failed"<<endl;
//             exit(2); 
//         }
//         return true;
//     }
//     void start()
//     {
//         //从这里开始就要开始接受数据了
//         char buffer[1024];
//         while(true)
//         {
//             struct sockaddr_in client;
//             bzero(&client,sizeof(client));
//             socklen_t len=sizeof(client);
//             char result[1024];
//             char key[256];
//             ssize_t s=recvfrom(_sock,buffer,sizeof(buffer),0,(struct sockaddr*)&client,&len);
//             if(s > 0)
//             {
//                 buffer[s]=0;
//                 uint16_t client_port=ntohs(client.sin_port);
//                 string ip=inet_ntoa(client.sin_addr);
//                 snprintf(key,sizeof(key),"%s-%u",key);
//                 auto it=_users.find(key);
//                 //维护一个用户列表
//                 if(it==_users.end())
//                 {
//                     _users.insert({key,client});
//                 }
//             }
//             for(auto& iter:_users)
//             {
//                 string sendMessage=key;
//                 sendMessage+="#";
//                 sendMessage+=buffer;
//                 //再把数据发送回给客户端
//                 sendto(_sock,sendMessage.c_str(),sizeof(sendMessage),0,(struct sockaddr*)&client,len);
//             }
//         }
//     }
//     ~UdpServer()
//     {
//         if(_sock >= 0)
//         {
//             close(_sock);
//         }
//     }
// private:
//     int _sock;
//     string _ip;
//     uint16_t _port;
//     unordered_map<string ,struct sockaddr_in> _users;
// };
// class UdpServer
// {
// public:
//     UdpServer(string ip="",uint16_t port)
//     :_ip(ip)
//     ,_port(port)
//     ,_sock(-1)
//     {

//     }
//     bool initServer()
//     {
//         _sock=socket(AF_INET,SOCK_DGRAM,0);

//     }
// private:
//     int _sock;
//     string _ip;
//     uint16_t _port;
//     unordered_map<string,struct sockaddr_in> _users;
// };
// class UdpServer
// {
// public:
//     UdpServer(string ip, uint16_t port)
//         : _ip(ip), _port(port)
//     {
//     }
//     bool InitServer()
//     {
//         _sock = socket(AF_INET, SOCK_DGRAM, 0);
//         if (_sock < 0)
//         {
//             cout << "InitServer failed" << endl;
//             exit(1);
//         }
//         struct sockaddr_in server;
//         socklen_t len = sizeof(server);
//         bzero(&server, sizeof(server));
//         server.sin_family = AF_INET;
//         server.sin_port = htons(_port);
//         server.sin_addr.s_addr = INADDR_ANY;
//         int ret = bind(_sock, (struct sockaddr *)&server, len);
//         if (ret < 0)
//         {
//             cout << "bind() failed" << endl;
//             close(_sock);
//             exit(2);
//         }
//     }
//     void start()
//     {
//         char buffer[1024];
//         char key[1024];
//         char result[1024];
//         struct sockaddr_in client;
//         socklen_t len = sizeof(client);
//         while (true)
//         {
//             ssize_t s = recvfrom(_sock, buffer, sizeof(buffer), 0, &client, &len);
//             if (s > 0)
//             {
//                 buffer[s] = 0;
//                 uint16_t client_port = ntohs(client.sin_port);
//                 string client_ip = inet_ntoa(client.sin_addr);
//                 snprintf(key,sizeof(key),"%s-%u",client_ip,client_port);
//                 auto it=_users.find(key);
//                 if(it==_users.end())
//                 {
//                     _users.insert({key,client});
//                 }
//             }
//         }
//     }

// private:
//     int _sock;
//     string _ip;
//     uint16_t _port;
//     unordered_map<string, struct sockaddr_in> _users;
// };
